/*******************************************************************************
 * Copyright (c) 2005, 2014 springside.github.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 *******************************************************************************/
package org.whuims.service.standard;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.persistence.DynamicSpecifications;
import org.springside.modules.persistence.SearchFilter;
import org.springside.modules.persistence.SearchFilter.Operator;
import org.whuims.entity.QuotaContext;
import org.whuims.entity.Standard;
import org.whuims.repository.jpa.StandardDao;

import java.util.*;

// Spring Bean的标识.
@Component
// 类中所有public函数都纳入事务管理的标识.
@Transactional
public class StandardService {

    private StandardDao standardDao;

    public Standard getStandard(Long id) {
        return standardDao.findOne(id);
    }

    public void save(Standard entity) {
        standardDao.save(entity);
    }

    public void delete(Long id) {
        standardDao.delete(id);
    }

    public List<Standard> getAllStandards() {
        return (List<Standard>) standardDao.findAll();
    }

    public List<Standard> findTopStandards(int size) {
        Sort sort = new Sort(Direction.DESC, "id");
        PageRequest pr = new PageRequest(0, size, sort);
        return standardDao.findAll(pr).getContent();
    }

    public Page<Standard> getStandardList(Map<String, Object> searchParams, int pageNumber, int pageSize,
                                          String sortType) {
        PageRequest pageRequest = buildPageRequest(pageNumber, pageSize, sortType);
        if (searchParams != null) {
            Specification<Standard> spec = buildSpecification(searchParams);
            return standardDao.findAll(spec, pageRequest);
        }
        return standardDao.findAll(pageRequest);
    }

    public Page<Standard> getStandardListByQuota(String keyword, int pageNumber, int pageSize,
                                                 String sortType) {
        PageRequest pageRequest = buildPageRequest(pageNumber, pageSize, sortType);
        Map<String, SearchFilter> filters = new HashMap<String, SearchFilter>();
        filters.put("quotas", new SearchFilter("quotas", Operator.LIKE, keyword));
        Specification<Standard> spec = DynamicSpecifications.bySearchFilter(filters.values(), Standard.class);
        return standardDao.findAll(spec, pageRequest);
    }

    public List<Standard> getRefStandards(Standard std) {
        String temp = std.getReference();
        String[] array = temp.split(";");
        List<Standard> result = new ArrayList<Standard>();
        for (String str : array) {
            Iterable<Standard> iter = standardDao.findByName(str);
            Standard rstd = null;
            if (iter.iterator().hasNext()) {
                rstd = iter.iterator().next();
            }
            if (rstd != null)
                result.add(rstd);
        }
        return result;
    }

    /**
     * 创建分页请求.
     */
    private PageRequest buildPageRequest(int pageNumber, int pagzSize, String sortType) {
        Sort sort = null;
        if (sortType == null) sortType = "auto";
        if ("auto".equals(sortType)) {
            sort = new Sort(Direction.DESC, "id");
        } else if ("title".equals(sortType)) {
            sort = new Sort(Direction.ASC, "name");
        }
        return new PageRequest(pageNumber - 1, pagzSize, sort);
    }

    /**
     * 创建动态查询条件组合.
     */
    private Specification<Standard> buildSpecification(Map<String, Object> searchParams) {
        Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
        filters.put("valid", new SearchFilter("valid", Operator.EQ, 1));
        Specification<Standard> spec = DynamicSpecifications.bySearchFilter(filters.values(), Standard.class);
        return spec;
    }

    @Autowired
    public void setStandardDao(StandardDao standardDao) {
        this.standardDao = standardDao;
    }

    public Set<String> detectQuotaStrs(Standard std) {
        String quotasStr = std.getQuotas();
        String[] array = quotasStr.split("\\s+");
        Set<String> result = new HashSet<String>();
        for (String str : array) {
            str = str.trim();
            if (str.length() > 1)
                result.add(str);
        }
        return result;
    }

    public List<QuotaContext> detectQuotaContexts(Standard std, Set<String> quotaStrList) {
        List<QuotaContext> result = new ArrayList<QuotaContext>();
        String bunch = std.getTextOcr();
        if (bunch == null) {
            return result;
        }
        Map<String, List<String>> qMap = new HashMap<String, List<String>>();
        for (String str : quotaStrList) {
            qMap.put(str, new ArrayList<String>());
        }
        for (String str : bunch.split("</?p>")) {
            for (String quota : quotaStrList) {
                if (str.contains(quota)) {
                    if (str.matches(".+?[0-9].+?") || str.matches(".+?[a-zA-Z].+?"))
                        qMap.get(quota).add(str);
                }
            }
        }
        for (Map.Entry<String, List<String>> entry : qMap.entrySet()) {
            QuotaContext qc = new QuotaContext();
            qc.setId(std.getId());
            qc.setQuota(entry.getKey());
            qc.setContexts(entry.getValue());
            result.add(qc);
        }
        return result;
    }
}
